#include "UART.h"

#define time_out 10000
#define normal_buf_size 30

UARTx_Typedef *UART1 = NULL;
UARTx_Typedef *UART2 = NULL;
UARTx_Typedef *UART3 = NULL;

UARTx_Typedef* UART_pointer(USART_TypeDef* USARTx)
{
    if(USARTx == USART1)
    {
        return UART1;
    }
    else if(USARTx == USART2)
    {
        return UART2;
    }
    else if(USARTx == USART3)
    {
        return UART3;
    }
}

void UARTx_init(USART_TypeDef *USARTx, uint32_t baud)
{
    uint16_t i;
    USART_InitTypeDef USART_InitStruct;
    GPIO_InitTypeDef GPIO_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    UARTx_Typedef *UARTx;

    // 时钟初始化
    if ((USARTx == USART1 || USARTx == USART2) && IS_BIT_0(RCC->APB2ENR, BIT(2)))
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    }
    else if (USARTx == USART3 && IS_BIT_0(RCC->APB2ENR, BIT(3)))
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    }
    if (IS_BIT_0(RCC->APB2ENR, BIT(0)))
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    }
    if (USARTx == USART1 && IS_BIT_0(RCC->APB2ENR, BIT(14)))
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    }
    else if (USARTx == USART2 && IS_BIT_0(RCC->APB1ENR, BIT(17)))
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    }
    else if (USARTx == USART3 && IS_BIT_0(RCC->APB1ENR, BIT(18)))
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    }

    // USART 初始化
    USART_StructInit(&USART_InitStruct);
    USART_InitStruct.USART_BaudRate = baud;
    USART_Init(USARTx, &USART_InitStruct);

    // UARTx 初始化及指针指向

    // USART1 PA9->TX PA10->RX
    if (USARTx == USART1)
    {
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA, &GPIO_InitStruct);
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStruct);

        NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;

        if(UART1 != NULL)
        {
            free(UART1->BUF_TEMP);
            free(UART1);
        }
        UART1 = malloc(sizeof(UARTx_Typedef));
        UARTx = UART1;
        i = UART1_BUF_SIZE;
    }
    // USART2 PA2->TX PA3->RX
    else if (USARTx == USART2)
    {
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA, &GPIO_InitStruct);
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStruct);

        NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;

        if(UART2 != NULL)
        {
            free(UART2->BUF_TEMP);
            free(UART2);
        }
        UART2 = malloc(sizeof(UARTx_Typedef));
        UARTx = UART2;
        i = UART2_BUF_SIZE;
    }
    // USART3 PB10->TX PB11->RX
    else if (USARTx == USART3)
    {
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOB, &GPIO_InitStruct);
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOB, &GPIO_InitStruct);

        NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;

        if(UART3 != NULL)
        {
            free(UART3->BUF_TEMP);
            free(UART3);
        }
        UART3 = malloc(sizeof(UARTx_Typedef));
        UARTx = UART3;
        i = UART3_BUF_SIZE;
    }

    UARTx->send_flag = false;
    UARTx->BUF_SIZE = i;
    UARTx->BUF_TEMP = malloc(UARTx->BUF_SIZE * sizeof(uint8_t));
    for (i = 0; i < UARTx->BUF_SIZE; i++)
    {
        UARTx->BUF_TEMP[i] = 0;
    }
    UARTx->BUF_POINTER_BEGIN = UARTx->BUF_POINTER_END = 0;

    // 中断配置
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
    NVIC_Init(&NVIC_InitStruct);

    // 初始化结构体

    USART_ITConfig(USARTx, USART_IT_TC, ENABLE);   // 开启中断
    USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); // 开启中断
    USART_Cmd(USARTx, ENABLE);                     // 启动
}

bool UARTx_sendByte(USART_TypeDef *USARTx, const uint8_t byte)
{
    uint16_t count = 0;
    USART_SendData(USARTx, byte);
    UARTx_Typedef *UARTx = NULL;

    if(USARTx == USART1)
    {
        UARTx = UART1;
    }
    else if(USARTx == USART2)
    {
        UARTx = UART2;
    }
    else if(USARTx == USART3)
    {
        UARTx = UART3;
    }

    while (!UARTx->send_flag)
    {
        count++;
        if (count > time_out)
        {
            return false;
        }
    }

    UARTx->send_flag = false;
    return true;
}

bool UARTx_sendString(USART_TypeDef *USARTx, uint8_t *str)
{
    while (*str)
    {
        if (!UARTx_sendByte(USARTx, *str))
        {
            return false;
        }
        str++;
    }
    return true;
}

bool UARTx_receiveString(USART_TypeDef *USARTx, uint8_t **str)
{
    uint8_t i;
    uint16_t buf_num;
    UARTx_Typedef *UARTx;

    if(USARTx == USART1)
    {
        UARTx = UART1;
    }
    else if(USARTx == USART2)
    {
        UARTx = UART2;
    }
    else if(USARTx == USART3)
    {
        UARTx = UART3;
    }

    buf_num = UARTx_bufAvailable(UARTx);
    Delay_ms(1);
    if (buf_num == 0)
    {
        return false;
    }
    else if (buf_num != UARTx_bufAvailable(UARTx))
    {
        return false;
    }
    if (*str != NULL)
    {
        free(*str);
    }
    *str = (uint8_t *)malloc(sizeof(uint8_t) * (buf_num + 1));
    for (i = 0; i < buf_num; i++)
    {
        (*str)[i] = UARTx->BUF_TEMP[UARTx->BUF_POINTER_BEGIN];
        UARTx->BUF_POINTER_BEGIN = (UARTx->BUF_POINTER_BEGIN + 1) % UARTx->BUF_SIZE;
    }
    (*str)[buf_num] = '\0';
    return true;
}

void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE))
    {
        if (UARTx_bufAvailable(UART1) >= UART1->BUF_SIZE)
        {
            UART1->BUF_POINTER_END = UART1->BUF_POINTER_BEGIN;
        }
        UART1->BUF_TEMP[UART1->BUF_POINTER_END] = USART_ReceiveData(USART1);
        UART1->BUF_POINTER_END = (UART1->BUF_POINTER_END + 1) % UART1->BUF_SIZE;
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
    else if (USART_GetITStatus(USART1, USART_IT_TC))
    {
        UART1->send_flag = true;
        USART_ClearITPendingBit(USART1, USART_IT_TC);
    }
}

void USART2_IRQHandler(void)
{
    if (USART_GetITStatus(USART2, USART_IT_RXNE))
    {
        if (UARTx_bufAvailable(UART2) >= UART1->BUF_SIZE)
        {
            UART2->BUF_POINTER_END = UART2->BUF_POINTER_BEGIN;
        }
        UART2->BUF_TEMP[UART2->BUF_POINTER_END] = USART_ReceiveData(USART2);
        UART2->BUF_POINTER_END = (UART2->BUF_POINTER_END + 1) % UART2->BUF_SIZE;
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    }
    else if (USART_GetITStatus(USART2, USART_IT_TC))
    {
        UART2->send_flag = true;
        USART_ClearITPendingBit(USART2, USART_IT_TC);
    }
}

void USART3_IRQHandler(void)
{
    if (USART_GetITStatus(USART3, USART_IT_RXNE))
    {
        if (UARTx_bufAvailable(UART3) >= UART3->BUF_SIZE)
        {
            UART3->BUF_POINTER_END = UART3->BUF_POINTER_BEGIN;
        }
        UART3->BUF_TEMP[UART3->BUF_POINTER_END] = USART_ReceiveData(USART3);
        UART3->BUF_POINTER_END = (UART3->BUF_POINTER_END + 1) % UART3->BUF_SIZE;
        USART_ClearITPendingBit(USART3, USART_IT_RXNE);
    }
    else if (USART_GetITStatus(USART3, USART_IT_TC))
    {
        UART3->send_flag = true;
        USART_ClearITPendingBit(USART3, USART_IT_TC);
    }
}
